home *** CD-ROM | disk | FTP | other *** search
/ Apple WWDC 1996 / WWDC96_1996 (CD).toast / Technology Materials / MacApp Release 10 / MacApp Release 10 - HD Ready / Libraries / Framework / Sources / UCommand.cp < prev    next >
Encoding:
Text File  |  1996-04-03  |  29.6 KB  |  1,038 lines  |  [TEXT/MPS ]

  1. //----------------------------------------------------------------------------------------
  2. // UCommand.cp 
  3. // Copyright © 1985-96 by Apple Computer, Inc. All rights reserved.
  4. //----------------------------------------------------------------------------------------
  5.  
  6. #ifndef __UCOMMAND__
  7. #include "UCommand.h"
  8. #endif
  9.  
  10. // MacApp
  11.  
  12. #ifndef __UAPPLEEVENTS__
  13. #include "UAppleEvents.h"
  14. #endif
  15.  
  16. #ifndef __UCLIPBOARDMGR__
  17. #include "UClipboardMgr.h"
  18. #endif
  19.  
  20. #ifndef __UCOMMANDHANDLER__
  21. #include "UCommandHandler.h"
  22. #endif
  23.  
  24. #ifndef __UCOREERRORMGR__
  25. #include "UCoreErrorMgr.h"
  26. #endif
  27.  
  28. #ifndef __UCOREGLOBALS__
  29. #include "UCoreGlobals.h"
  30. #endif
  31.  
  32. #ifndef __UCOREUTILITIES__
  33. #include "UCoreUtilities.h"
  34. #endif
  35.  
  36. #ifndef __UDEBUG__
  37. #include "UDebug.h"
  38. #endif
  39.  
  40. #ifndef __UDEPENDENCIES__
  41. #include "UDependencies.h"
  42. #endif
  43.  
  44. #ifndef __UDISPATCHER__
  45. #include "UDispatcher.h"
  46. #endif
  47.  
  48. #ifndef __UDOCUMENT__
  49. #include "UDocument.h"
  50. #endif
  51.  
  52. //    #ifndef __UERRORMGR__
  53. //    #include "UErrorMgr.h"
  54. //    #endif
  55.  
  56. #ifndef __UGEOMETRY__
  57. #include "UGeometry.h"
  58. #endif
  59.  
  60. #ifndef __UMACAPPGLOBALS__
  61. #include "UMacAppGlobals.h"
  62. #endif
  63.  
  64. #ifndef __UMACAPPUTILITIES__
  65. #include "UMacAppUtilities.h"
  66. #endif
  67.  
  68. #ifndef __UMEMORY__
  69. #include "UMemory.h"
  70. #endif
  71.  
  72. #ifndef __USCRIPTING__
  73. #include "UScripting.h"
  74. #endif
  75.  
  76. //    #ifndef __USCROLLER__
  77. //    #include "UScroller.h"
  78. //    #endif
  79.  
  80. #ifndef __USEGMENTS__
  81. #include "USegments.h"
  82. #endif
  83.  
  84. #ifndef __UVIEW__
  85. #include "UView.h"
  86. #endif
  87.  
  88. //    #ifndef __UWINDOW__
  89. //    #include "UWindow.h"
  90. //    #endif
  91.  
  92. // Toolbox
  93.  
  94. #ifndef __LOWMEM__
  95. #include <LowMem.h>
  96. #endif
  97.  
  98. #ifndef __OSEVENTS__
  99. #include <OSEvents.h>
  100. #endif
  101.  
  102. // ANSI
  103.  
  104. #ifndef __STDIO__
  105. #include <stdio.h>
  106. #endif
  107.  
  108. #ifndef __STDLIB__
  109. #include <stdlib.h>
  110. #endif
  111.  
  112. //========================================================================================
  113. // Global Functions
  114. //========================================================================================
  115. #pragma segment MACommandRes
  116.  
  117. TCommand* CommitACommand(TCommand *aCommand)
  118. {    
  119.     if (aCommand)
  120.     {
  121. #if qDebug
  122.         if (!VerboseIsObject(aCommand))
  123.         {
  124.             ProgramBreak("In CommitCompletedCommand: Not handed a valid object");
  125.             return NULL;
  126.         }
  127. #endif
  128.         //    if (aCommand->fCommandDone)
  129.         //        aCommand->Commit();
  130.             
  131.         aCommand->Completed();
  132.         
  133.         if (aCommand->ShouldFreeOnCompletion())
  134.             FreeIfObject(aCommand);
  135.     }
  136.         
  137.     return NULL;
  138. }
  139.  
  140. //========================================================================================
  141. // CLASS TCommand
  142. //========================================================================================
  143. #undef Inherited
  144. #define Inherited TEvent
  145.  
  146. #pragma segment MACommandNonRes
  147. MA_DEFINE_CLASS_M1(TCommand, Inherited);
  148.  
  149. //----------------------------------------------------------------------------------------
  150. // TCommand constructor
  151. //----------------------------------------------------------------------------------------
  152. #pragma segment MACommandRes
  153.  
  154. TCommand::TCommand()
  155.     : fObjectToNotify(NULL),
  156.       fContext(NULL),
  157. //      fLinkedCommand(NULL),
  158. //      fLinkIdentity(kNotLinked),
  159.       fCommandDone(FALSE),
  160.       fCanUndo(TRUE),
  161.       fCausesChange(TRUE),
  162.       fChangesClipboard(FALSE),
  163.       fClipboardView(NULL),
  164.       fUndoClipboardView(NULL),
  165.       fUndoClipboardViewContext(NULL),
  166.       fFreeOnCompletion(TRUE),                // command will be freed after DoIt or Commit
  167.       fRecurring(FALSE),                    // Command is a one-shot deal 
  168.       fReadyToExecute(TRUE),                // Always executable by default 
  169.       fValidationError(noErr),                // Hasn't failed yet...
  170.       fUseAppleEvent(FALSE)
  171. {
  172. }
  173.  
  174. //----------------------------------------------------------------------------------------
  175. // TCommand::ICommand:
  176. //----------------------------------------------------------------------------------------
  177. #pragma segment MACommandRes
  178.  
  179. void TCommand::ICommand(CommandNumber itsCommandNumber,
  180.                                TCommandHandler* itsContext,    // Typically a document or a document-less view
  181.                                Boolean canUndo,
  182.                                Boolean causesChange,
  183.                                TObject* objectToNotify)    // Typically the context
  184. {
  185.     TCommandHandler* theContext = itsContext;
  186.     if (itsContext == NULL)
  187.         theContext = gDispatcher;
  188.  
  189.     this->IEvent(itsCommandNumber, NULL, theContext);
  190.  
  191.     fIdentifier = itsCommandNumber;
  192.     fCanUndo = canUndo;
  193.     fCausesChange = causesChange;
  194.     fObjectToNotify = objectToNotify;
  195.     fContext = theContext;
  196. }
  197.  
  198. //----------------------------------------------------------------------------------------
  199. // TCommand::Free:
  200. //----------------------------------------------------------------------------------------
  201. #pragma segment MADoCommand
  202.  
  203. TCommand::~TCommand()
  204. {
  205.     if (fChangesClipboard)
  206.     {
  207.         this->AbandonClipboardView();                        
  208.         this->AbandonUndoClipboardView();                        
  209.     }
  210.     
  211.     // If this command is in the action history, it should
  212.     // be freed only through the undo handler, so the
  213.     // action history can be cleaned up before the command is freed. 
  214.     
  215.     //    this->LinkToSecondary(NULL); // clear the reference to this command in its linked cmd
  216. }
  217.  
  218. //----------------------------------------------------------------------------------------
  219. // TCommand::AbandonClipboardView
  220. //----------------------------------------------------------------------------------------
  221. #pragma segment MADoCommand
  222.  
  223. void TCommand::AbandonClipboardView() // override
  224. {
  225. //    fClipboardView is owned by this command, which created it, unless it
  226. //    is the current clipboard, in which case it is owned by gClipboardMgr.
  227.  
  228. // Note:: TView::FreeFromClipboard calls gClipboardMgr->Changed
  229. // so that if another command has a reference to this fClipboardView
  230. // in its fUndoClipboardView field, it can NULL it.
  231.  
  232.     if (fClipboardView)
  233.     {
  234.         if (fClipboardView == gClipboardMgr->fClipView)
  235.             gClipboardMgr->fClipContext = NULL;
  236.         else
  237.         {
  238.             fClipboardView->FreeFromClipboard();
  239.             fClipboardView = NULL;
  240.         }
  241.     }
  242. }
  243.  
  244. //----------------------------------------------------------------------------------------
  245. // TCommand::AbandonClipboardView
  246. //----------------------------------------------------------------------------------------
  247. #pragma segment MADoCommand
  248.  
  249. void TCommand::AbandonUndoClipboardView()  
  250. {
  251. // Note:: TView::FreeFromClipboard calls gClipboardMgr->Changed
  252. // so that if another command has a reference to this fUndoClipboardView
  253. // in its fClipboardView field, it can NULL it.
  254.  
  255.     if (fUndoClipboardView 
  256.         && (fUndoClipboardView != gClipboardMgr->fClipView)
  257.         && ((fUndoClipboardViewContext == NULL) || (fUndoClipboardViewContext == fContext))    )
  258.     {
  259.         fUndoClipboardView->FreeFromClipboard();
  260.         fUndoClipboardView = NULL;
  261.     }
  262. }
  263.  
  264. //----------------------------------------------------------------------------------------
  265. // TCommand::PrepareForUndoRedo:
  266. //----------------------------------------------------------------------------------------
  267. #pragma segment MADoCommand
  268.  
  269. void TCommand::PrepareForUndoRedo()
  270. {
  271.     if (fContext)
  272.         fContext->PrepareForUndoRedo(this);
  273. }
  274.  
  275. //----------------------------------------------------------------------------------------
  276. // TCommand::FinishUndoRedo:
  277. //----------------------------------------------------------------------------------------
  278. #pragma segment MADoCommand
  279.  
  280. void TCommand::FinishUndoRedo()
  281. {
  282.     if (fChangesClipboard)
  283.         UndoRedoClipboard();
  284.     
  285.     fCommandDone = !fCommandDone;
  286.     DoNotification();
  287. }
  288.  
  289. //----------------------------------------------------------------------------------------
  290. // TCommand::RevealUndoRedo:
  291. //----------------------------------------------------------------------------------------
  292. #pragma segment MADoCommand
  293.  
  294. void TCommand::RevealUndoRedo()
  295. {
  296.     if (fContext)
  297.         fContext->RevealUndoRedo(this);
  298. }
  299.  
  300. //----------------------------------------------------------------------------------------
  301. // TCommand::Commit:
  302. //----------------------------------------------------------------------------------------
  303. //    #pragma segment MADoCommand
  304.     
  305. //    void TCommand::Commit()
  306. //    {
  307. //    }
  308.  
  309. //----------------------------------------------------------------------------------------
  310. // TCommand::Completed:
  311. //----------------------------------------------------------------------------------------
  312. #pragma segment MADoCommand
  313.  
  314. void TCommand::Completed()
  315. {
  316. }
  317.  
  318. //----------------------------------------------------------------------------------------
  319. // TCommand::DoIt:
  320. //----------------------------------------------------------------------------------------
  321. #pragma segment MADoCommand
  322.  
  323. void TCommand::DoIt()
  324. {
  325. }
  326.  
  327. //----------------------------------------------------------------------------------------
  328. // TCommand::GetChangeID:
  329. //----------------------------------------------------------------------------------------
  330. #pragma segment MACommandRes
  331.  
  332. ChangeID TCommand::GetChangeID()
  333. {
  334.     return fIdentifier;
  335. }
  336.  
  337. //----------------------------------------------------------------------------------------
  338. // TCommand::CanBeUndone:
  339. //----------------------------------------------------------------------------------------
  340. #pragma segment MACommandRes
  341.  
  342. Boolean TCommand::CanBeUndone()
  343. {
  344.     return fCanUndo;
  345. }
  346.  
  347. //----------------------------------------------------------------------------------------
  348. // TCommand::IsReadyToExecute:
  349. //----------------------------------------------------------------------------------------
  350. #pragma segment MACommandRes
  351.  
  352. Boolean TCommand::IsReadyToExecute() // override
  353. {
  354.     return fReadyToExecute;
  355. }
  356.  
  357. //----------------------------------------------------------------------------------------
  358. // TCommand::IsRecurring:
  359. //----------------------------------------------------------------------------------------
  360. #pragma segment MACommandRes
  361.  
  362. Boolean TCommand::IsRecurring() // override
  363. {
  364.     return fRecurring;
  365. }
  366.  
  367. //----------------------------------------------------------------------------------------
  368. // TCommand::WillCauseChange:
  369. //----------------------------------------------------------------------------------------
  370. #pragma segment MACommandRes
  371.  
  372. Boolean TCommand::WillCauseChange()
  373. {
  374.     return fCausesChange;
  375. }
  376.  
  377. //----------------------------------------------------------------------------------------
  378. // TCommand::MakeAppleEvent:
  379. //----------------------------------------------------------------------------------------
  380. #pragma segment MACommandRes
  381.  
  382. TAppleEvent* TCommand::MakeAppleEvent()
  383. {
  384.     return NULL;
  385. }
  386.  
  387. //----------------------------------------------------------------------------------------
  388. // TCommand::DoNotification:
  389. //----------------------------------------------------------------------------------------
  390. #pragma segment MACommandRes
  391.  
  392. void TCommand::DoNotification()
  393. {
  394.     // Notify the proper object that a change has occurred     
  395.     if (this->WillCauseChange() && fObjectToNotify)
  396.     {
  397.         ChangeID theChange;
  398.         if (fCommandDone)
  399.             theChange = this->GetChangeID();
  400.         else
  401.             theChange = cUndo;
  402.         fObjectToNotify->Changed(theChange, this);
  403.     }
  404. }
  405.  
  406. //----------------------------------------------------------------------------------------
  407. // TCommand::SetupDependencies:
  408. //----------------------------------------------------------------------------------------
  409. #pragma segment MACommandRes
  410.  
  411. void TCommand::SetupDependencies()
  412. {
  413.     if (this->CanBeUndone())
  414.     {
  415.         fContext->AddDependent(this);
  416.         if (fChangesClipboard || (fIdentifier == cPaste))
  417.             gClipboardMgr->AddDependent(this);
  418.     }
  419. }
  420.  
  421. //----------------------------------------------------------------------------------------
  422. // TCommand::DoUpdate:
  423. //----------------------------------------------------------------------------------------
  424. #pragma segment MACommandRes
  425.  
  426. void TCommand::DoUpdate(ChangeID theChange,
  427.                         TObject* changedObject,
  428.                         TObject* changedBy,
  429.                         TDependencySpace* /* dependencySpace */) // override
  430. {
  431.     switch (theChange)
  432.     {
  433.         case mClipViewChanged:
  434.             // This code appears to be there to support Paste commands
  435.             // whose RedoIt methods go back to the clipboard document for the
  436.             // data to paste. *** This won't work with multiple undo. ***
  437.             // From now on, commands need to save all the data needed for 
  438.             // their UndoIt and RedoIt methods. 
  439.             
  440.             //    if ((changedObject == gClipboardMgr) &&
  441.             //        (fIdentifier == cPaste))
  442.             //        fContext->CommitLastCommand();
  443.             break;
  444.  
  445.         case mFreeClipboardView:
  446.             if (changedObject == gClipboardMgr) 
  447.                 if (changedBy == fUndoClipboardView)
  448.                 {
  449.                     fUndoClipboardView = NULL;
  450.                     fUndoClipboardViewContext = NULL;
  451.                 }
  452.                 else if (changedBy == fClipboardView)
  453.                     fClipboardView = NULL;
  454.             break;
  455.  
  456.         case mClosed:
  457.             if ((changedObject == fContext)
  458.                 /* || (theChange == mAboutToLoseControl) */
  459.                 || (theChange == mScrapChanged)) 
  460.                 fContext->CommitLastCommand();
  461.             break;
  462.     }
  463. }
  464.  
  465. //----------------------------------------------------------------------------------------
  466. // TCommand::RedoIt:
  467. //----------------------------------------------------------------------------------------
  468. #pragma segment MADoCommand
  469.  
  470. void TCommand::RedoIt()
  471. {
  472.     this->DoIt();
  473. }
  474.  
  475. //----------------------------------------------------------------------------------------
  476. // TCommand::ShouldFreeOnCompletion:
  477. //----------------------------------------------------------------------------------------
  478. #pragma segment MACommandRes
  479.  
  480. Boolean TCommand::ShouldFreeOnCompletion()
  481. {
  482.     return (!fRecurring && fFreeOnCompletion);
  483. }
  484.  
  485. //----------------------------------------------------------------------------------------
  486. // TCommand::UndoIt:
  487. //----------------------------------------------------------------------------------------
  488. #pragma segment MADoCommand
  489.  
  490. void TCommand::UndoIt()
  491. {
  492. }
  493.  
  494. //----------------------------------------------------------------------------------------
  495. // TCommand::Process:
  496. //----------------------------------------------------------------------------------------
  497. #pragma segment MACommandRes
  498.  
  499. void TCommand::Process()    
  500. {
  501.     if (fContext)
  502.         fContext->PerformCommand(this);
  503. }
  504.  
  505. //----------------------------------------------------------------------------------------
  506. // TCommand::NeedsToUnloadAllSegments:
  507. //----------------------------------------------------------------------------------------
  508. #pragma segment MACommandRes
  509.  
  510. Boolean TCommand::NeedsToUnloadAllSegments()    
  511. {
  512.     return TRUE;
  513. }
  514.  
  515. //----------------------------------------------------------------------------------------
  516. // TCommand::LinkToSecondary:
  517. //----------------------------------------------------------------------------------------
  518. #pragma segment MACommandRes
  519.  
  520. //----------------------------------------------------------------------------------------
  521. // TCommand::SetValidationError:
  522. //----------------------------------------------------------------------------------------
  523. #pragma segment MACommandRes
  524.  
  525. void TCommand::SetValidationError(OSErr    validationError)
  526. {
  527.     fValidationError = validationError;
  528.     //    if (fLinkedCommand)
  529.     //        fLinkedCommand->fValidationError = validationError;
  530. }
  531.  
  532. //----------------------------------------------------------------------------------------
  533. // TCommand::Abort:
  534. //----------------------------------------------------------------------------------------
  535. #pragma segment MACommandRes
  536.  
  537. void TCommand::Abort()
  538. {
  539.     // Try to remove the command in case it is no longer recurring.
  540.     gDispatcher->RemoveEvent(this);
  541.     
  542.     if ((gClipboardMgr->fClipView != NULL) &&
  543.         (gClipboardMgr->fClipView == fClipboardView))
  544.     {
  545.         gClipboardMgr->SetClipView(fUndoClipboardView, fUndoClipboardViewContext);
  546.         fUndoClipboardView = NULL;
  547.     }
  548.  
  549.     if (fCommandDone && CanBeUndone())
  550.     {
  551.         UndoIt();
  552.         if (fChangesClipboard)
  553.             UndoRedoClipboard();
  554.         fCommandDone = FALSE;
  555.         DoNotification();
  556.     }
  557.     
  558.     Completed();
  559. }
  560.  
  561. //----------------------------------------------------------------------------------------
  562. // TCommand::ClaimClipboard:
  563. //----------------------------------------------------------------------------------------
  564. #pragma segment MACommandRes
  565.  
  566. void TCommand::ClaimClipboard(TView* clipboardView)
  567. {
  568.     // For RedoIt only
  569.     this->AbandonUndoClipboardView();
  570.  
  571.     fUndoClipboardView = gClipboardMgr->fClipView;    // Copy current clipboard contents to the
  572.                                                     // Undo side
  573.     fUndoClipboardViewContext = fContext;            // gClipboardMgr->fClipContext; 
  574.     if (clipboardView)
  575.     {
  576.         gClipboardMgr->SetClipView(clipboardView, fContext);            // Will install it as fClipView 
  577.         fClipboardView = clipboardView;    
  578.     }    
  579. #if qDebugMsg
  580.     else
  581.         ProgramBreak("Claiming clipboard with NULL view");
  582. #endif
  583. }
  584.  
  585. //----------------------------------------------------------------------------------------
  586. // TCommand::UndoRedoClipboard:
  587. //----------------------------------------------------------------------------------------
  588. #pragma segment MACommandRes
  589.  
  590. void TCommand::UndoRedoClipboard()
  591. {    
  592.     if (fCommandDone)
  593.     {
  594.         // Undoing
  595.         if (fUndoClipboardView && (gClipboardMgr->fClipContext == fContext))
  596.         {
  597.             gClipboardMgr->SetClipView(fUndoClipboardView, fUndoClipboardViewContext);
  598.         }
  599.     }
  600.     else if (fValidationError == noErr)
  601.     {
  602.         // Redoing
  603.         this->ClaimClipboard(fClipboardView);        
  604.     }
  605. }
  606.  
  607. //========================================================================================
  608. // CLASS TAppleCommand
  609. //========================================================================================
  610. #undef Inherited
  611. #define Inherited TCommand
  612.  
  613. #pragma segment MACommandNonRes
  614. MA_DEFINE_CLASS_M1(TAppleCommand, Inherited);
  615.  
  616. //----------------------------------------------------------------------------------------
  617. // TAppleCommand constructor
  618. //----------------------------------------------------------------------------------------
  619. #pragma segment MACommandRes
  620.  
  621. TAppleCommand::TAppleCommand() :
  622.     fMessage(NULL),
  623.     fReply(NULL)
  624. {
  625. }
  626.  
  627. //----------------------------------------------------------------------------------------
  628. // TAppleCommand::IAppleCommand:
  629. //----------------------------------------------------------------------------------------
  630. #pragma segment MACommandRes
  631.  
  632. void TAppleCommand::IAppleCommand(CommandNumber itsCommandNumber,
  633.                                   TCommandHandler* itsContext,
  634.                                   Boolean canUndo,
  635.                                   Boolean causesChange,
  636.                                   TObject* objectToNotify)
  637. {
  638.     this->ICommand(itsCommandNumber, itsContext, canUndo, causesChange, objectToNotify);
  639. }
  640.  
  641. //----------------------------------------------------------------------------------------
  642. // TAppleCommand::IAppleCommand:
  643. //----------------------------------------------------------------------------------------
  644. #pragma segment MACommandRes
  645.  
  646. void TAppleCommand::IAppleCommand(CommandNumber itsCommandNumber,
  647.                                   TCommandHandler* itsContext,
  648.                                   Boolean canUndo,
  649.                                   Boolean causesChange,
  650.                                   TObject* objectToNotify,
  651.                                   TAppleEvent* message,
  652.                                   TAppleEvent* reply)
  653. {
  654.     this->ICommand(itsCommandNumber, itsContext,  canUndo,
  655.                    causesChange, objectToNotify);
  656.     fMessage = message;
  657.     fReply = reply;
  658. }
  659.  
  660. //----------------------------------------------------------------------------------------
  661. // TAppleCommand::Free:
  662. //----------------------------------------------------------------------------------------
  663. #pragma segment MADoCommand
  664.  
  665. TAppleCommand::~TAppleCommand()
  666. {
  667.     this->FreeTheMessage();                        // Properly free the events by resuming if necessary
  668. }
  669.  
  670. //----------------------------------------------------------------------------------------
  671. // TAppleCommand::FreeTheMessage:
  672. //----------------------------------------------------------------------------------------
  673. #pragma segment MADoCommand
  674.  
  675. void TAppleCommand::FreeTheMessage()
  676. {
  677.     fMessage = (TAppleEvent *)FreeIfObject(fMessage);
  678.     fReply = (TAppleEvent *)FreeIfObject(fReply);
  679. }
  680.  
  681. //========================================================================================
  682. // CLASS TServerCommand
  683. //========================================================================================
  684. #undef Inherited
  685. #define Inherited TAppleCommand
  686.  
  687. #pragma segment MACommandNonRes
  688. MA_DEFINE_CLASS_M1(TServerCommand, Inherited);
  689.  
  690. //----------------------------------------------------------------------------------------
  691. // TServerCommand constructor
  692. //----------------------------------------------------------------------------------------
  693. #pragma segment MACommandRes
  694.  
  695. TServerCommand::TServerCommand() :
  696.     fRequiresUserInteraction(FALSE),
  697.     fSuspendTheEvent(FALSE),
  698.     fReplySent(FALSE)
  699. {
  700. }
  701.  
  702. //----------------------------------------------------------------------------------------
  703. // TServerCommand destructor
  704. //----------------------------------------------------------------------------------------
  705. #pragma segment MADestructorRes
  706.  
  707. TServerCommand::~TServerCommand()
  708. {
  709. }
  710.  
  711. //----------------------------------------------------------------------------------------
  712. // TServerCommand::IServerCommand:
  713. //----------------------------------------------------------------------------------------
  714. #pragma segment MACommandRes
  715.  
  716. void TServerCommand::IServerCommand(CommandNumber itsCommandNumber,
  717.                                     TCommandHandler* itsContext,
  718.                                     Boolean canUndo,
  719.                                     Boolean causesChange,
  720.                                     TObject* objectToNotify)
  721. {
  722.     this->IAppleCommand(itsCommandNumber, itsContext, canUndo, causesChange, objectToNotify);
  723. }
  724.  
  725. //----------------------------------------------------------------------------------------
  726. // TServerCommand::IServerCommand:
  727. //----------------------------------------------------------------------------------------
  728. #pragma segment MACommandRes
  729.  
  730. void TServerCommand::IServerCommand(CommandNumber itsCommandNumber,
  731.                                     TCommandHandler* itsContext,
  732.                                     Boolean canUndo,
  733.                                     Boolean causesChange,
  734.                                     TObject* objectToNotify,
  735.                                     const AppleEvent& itsMessage,
  736.                                     const AppleEvent& itsReply)
  737. {
  738.     this->IAppleCommand(itsCommandNumber, itsContext, canUndo, causesChange, objectToNotify);
  739.  
  740.     FailInfo fi;
  741.     Try(fi)
  742.     {
  743.         // Inform the AppleEvent manager that this event will be processed asynchronously.
  744.         // Any reply that needs to be returned will be returned in TServerCommand::Completed().
  745.         if (fSuspendTheEvent)
  746.             AESuspendTheCurrentEvent(&itsMessage);
  747.  
  748.         TAppleEvent* aMessage = new TAppleEvent;
  749.         aMessage->InitializeFromMessage(itsMessage, FALSE);
  750.         fMessage = aMessage;
  751.  
  752.         TAppleEvent* aReply = new TAppleEvent;
  753.         aReply->InitializeFromMessage(itsReply, FALSE);
  754.         fReply = aReply;
  755.         
  756.         fi.Success();
  757.     }
  758.     else    // Recover
  759.     {
  760.         // TApplication::DispatchAppleEvent takes care of canceling the suspension of
  761.         // the message in case of failure so all we worry about here is freeing the command
  762.         this->Free();
  763.         
  764.         fi.ReSignal();
  765.     }
  766. }
  767.  
  768. //----------------------------------------------------------------------------------------
  769. // TServerCommand::IServerCommand:
  770. //----------------------------------------------------------------------------------------
  771. #pragma segment MACommandRes
  772.  
  773. void TServerCommand::IServerCommand(CommandNumber itsCommandNumber,
  774.                                     TCommandHandler* itsContext,
  775.                                     Boolean canUndo,
  776.                                     Boolean causesChange,
  777.                                     TObject* objectToNotify,
  778.                                     TAppleEvent* itsMessage,
  779.                                     TAppleEvent* itsReply)
  780. {
  781.     this->IAppleCommand(itsCommandNumber, itsContext, canUndo, causesChange, objectToNotify);
  782.  
  783.     FailInfo fi;
  784.     Try(fi)
  785.     {
  786.         // Inform the AppleEvent manager that this event will be processed asynchronously.
  787.         // Any reply that needs to be returned will be returned in TServerCommand::Completed().
  788.         if (fSuspendTheEvent)
  789.             AESuspendTheCurrentEvent(&itsMessage->fMessage);
  790.  
  791.         fMessage = itsMessage;
  792.         fReply = itsReply;
  793.         
  794.         fi.Success();
  795.     }
  796.     else    // Recover
  797.     {
  798.         // TApplication::DispatchAppleEvent takes care of canceling the suspension of
  799.         // the message in case of failure so all we worry about here is freeing the command
  800.         this->Free();
  801.         
  802.         fi.ReSignal();
  803.     }
  804. }
  805.  
  806. //----------------------------------------------------------------------------------------
  807. // TServerCommand::Completed:
  808. //----------------------------------------------------------------------------------------
  809. #pragma segment MADoCommand
  810.  
  811. void TServerCommand::Completed() // override
  812. {
  813.     if (fMessage && fReply)
  814.         this->ResumeAndFreeMessage();
  815. }
  816.  
  817. //----------------------------------------------------------------------------------------
  818. // TServerCommand::Process:
  819. //----------------------------------------------------------------------------------------
  820. #pragma segment MACommandRes
  821.  
  822. void TServerCommand::Process()
  823. {
  824.     if (fRequiresUserInteraction)
  825.     {
  826.         FailInfo fi1;
  827.         Try(fi1)
  828.         {
  829.             FailOSErr(MAInteractWithUser());
  830.             fi1.Success();
  831.         }
  832.         else
  833.         {
  834.             this->SetValidationError(fi1.error);
  835.             fi1.ReSignal();
  836.         }
  837.     }
  838.     FailInfo fi2;
  839.     Try(fi2)
  840.     {
  841.         Inherited::Process();
  842.         fi2.Success();
  843.     }
  844.     else
  845.     {
  846.         // If an error arose and a reply was sent then ignore the error
  847.         // at this point.
  848.         if (!fReplySent)
  849.         {
  850.             if (fi2.error == userCanceledErr)
  851.                 FailNewMessage(noErr, fi2.message, messageCancelled);
  852.             fi2.ReSignal();
  853.         }
  854.     }
  855. }
  856.  
  857. //----------------------------------------------------------------------------------------
  858. // TServerCommand::ResumeAndFreeMessage:
  859. //----------------------------------------------------------------------------------------
  860. #pragma segment MACommandRes
  861.  
  862. void TServerCommand::ResumeAndFreeMessage()
  863. {
  864.     // If the event has been suspended then resume it and free the message.
  865.     if (fSuspendTheEvent)
  866.     {
  867.         AppleEvent theMessage = fMessage->fMessage;
  868.         AppleEvent theReply = fReply->fMessage;
  869.         
  870.         // Inform the AppleEvent manager that we are through processing the event. If an error
  871.         // has occurred the default reply will contain the error number and error string.
  872.         AEEventHandlerUPP dispatcher = kAENoDispatch;
  873.  
  874.         AEResumeTheCurrentEvent(&theMessage, &theReply, dispatcher, 0);
  875.         fReplySent = TRUE;
  876.     }
  877.     // Free the message and its reply since they are no longer valid
  878.     this->FreeTheMessage();
  879. }
  880.  
  881. //----------------------------------------------------------------------------------------
  882. // TServerCommand::SetValidationError:
  883. //----------------------------------------------------------------------------------------
  884. #pragma segment MACommandRes
  885.  
  886. void TServerCommand::SetValidationError(OSErr error)
  887. {
  888.     // The finder passes a null reply with required events
  889.     // so don't try to stuff any info into the reply
  890.     if (fReply && fReply->fMessage.descriptorType != typeNull)
  891.         fReply->WriteOSError(error);
  892.     Inherited::SetValidationError(error);
  893. }
  894.  
  895. //========================================================================================
  896. // CLASS TClientCommand
  897. //========================================================================================
  898. #undef Inherited
  899. #define Inherited TAppleCommand
  900.  
  901. #pragma segment MACommandNonRes
  902. MA_DEFINE_CLASS_M1(TClientCommand, Inherited);
  903.  
  904. //----------------------------------------------------------------------------------------
  905. // TClientCommand constructor
  906. //----------------------------------------------------------------------------------------
  907. #pragma segment MACommandRes
  908.  
  909. TClientCommand::TClientCommand() :
  910.     fMessageSent(FALSE)
  911. {
  912. }
  913.  
  914. //----------------------------------------------------------------------------------------
  915. // TClientCommand destructor
  916. //----------------------------------------------------------------------------------------
  917. #pragma segment MADestructorRes
  918.  
  919. TClientCommand::~TClientCommand()
  920. {
  921. }
  922.  
  923. //----------------------------------------------------------------------------------------
  924. // TClientCommand::IClientCommand:
  925. //----------------------------------------------------------------------------------------
  926. #pragma segment MACommandRes
  927.  
  928. void TClientCommand::IClientCommand(CommandNumber itsCommandNumber,
  929.                                     TCommandHandler* itsContext,
  930.                                     Boolean canUndo,
  931.                                     Boolean causesChange,
  932.                                     TObject* objectToNotify,
  933.                                     TAppleEvent* theMessage)
  934. {
  935.     this->IAppleCommand(itsCommandNumber, itsContext, canUndo, causesChange, objectToNotify);
  936.     this->fMessage = theMessage;
  937. }
  938.  
  939. //----------------------------------------------------------------------------------------
  940. // TClientCommand::GetReturnID:
  941. //----------------------------------------------------------------------------------------
  942. #pragma segment MACommandRes
  943.  
  944. long TClientCommand::GetReturnID()
  945. {
  946.     if (fMessage)
  947.         return fMessage->GetReturnID();
  948.     else
  949.         return 0;
  950. }
  951.  
  952. //----------------------------------------------------------------------------------------
  953. // TClientCommand::IsReadyToPost:
  954. //----------------------------------------------------------------------------------------
  955. #pragma segment MACommandRes
  956.  
  957. Boolean TClientCommand::IsReadyToPost() // override
  958. {
  959.     Boolean ready = TRUE;
  960.     
  961.     if (fMessage)
  962.     {
  963.         if (!fMessageSent)
  964.         {
  965.             if ((fMessage->GetSendingMode() & kAEReplyModeMask) == kAEWaitReply)
  966.             {
  967.                 TAppleEvent* theReply = NULL;
  968.                 
  969.                 theReply = this->SendMessage();
  970.                 this->ProcessReply(theReply);
  971.             }
  972.             else if ((fMessage->GetSendingMode() & kAEReplyModeMask) == kAEQueueReply)
  973.             {
  974.                 this->SendMessage();    // No reply will be returned
  975.                 TOSADispatcher::fgDispatcher->PostPendingReplyCommand(this);
  976.                 ready = FALSE;
  977.             }
  978.         }
  979.         else if (((fMessage->GetSendingMode() & kAEReplyModeMask) == kAEQueueReply) && (fReply == NULL))
  980.             ready = FALSE;                // Even though the message has been sent we still
  981.                                         // haven't received our reply so don't post it yet.
  982.     }
  983.     return ready;
  984. }
  985.  
  986. //----------------------------------------------------------------------------------------
  987. // TClientCommand::SendMessage:
  988. //----------------------------------------------------------------------------------------
  989. #pragma segment MACommandRes
  990.  
  991. TAppleEvent* TClientCommand::SendMessage()
  992. {
  993.     if (fMessage)
  994.     {
  995.         fMessageSent = TRUE;
  996.         return fMessage->Send();
  997.     }
  998.     else
  999.         return NULL;
  1000. }
  1001.  
  1002. //----------------------------------------------------------------------------------------
  1003. // TClientCommand::ProcessReply:
  1004. //----------------------------------------------------------------------------------------
  1005. #pragma segment MACommandRes
  1006.  
  1007. void TClientCommand::ProcessReply(TAppleEvent* theReply)
  1008. {
  1009.     fReply = theReply;
  1010.     
  1011.     // Check for errors in the reply.
  1012.     long     errorNumber;
  1013.     CStr255    errorString;
  1014.     theReply->ReadError(errorNumber, errorString);
  1015.  
  1016.     if ((errorNumber != noErr) || !errorString.IsEmpty())
  1017.     {
  1018.         if (gDispatcher)
  1019.             gDispatcher->ReportReplyError(fIdentifier, (OSErr)errorNumber, errorString);
  1020.     }
  1021. }
  1022.  
  1023. //----------------------------------------------------------------------------------------
  1024. // TClientCommand::DoIt:
  1025. //----------------------------------------------------------------------------------------
  1026. #pragma segment MADoCommand
  1027.  
  1028. void TClientCommand::DoIt() // override
  1029. {
  1030.     if (fMessage && ((fMessage->GetSendingMode() & kAEReplyModeMask) == kAENoReply))
  1031.         this->SendMessage();
  1032. }
  1033.  
  1034. //----------------------------------------------------------------------------------------
  1035. // End of UCommand.cp
  1036.  
  1037. #pragma segment Inline
  1038.